home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 3 / Info_Mac_1994-01.iso / Development / Source / IRC client Source / ircle sources / MsgWindows.p < prev   
Encoding:
Text File  |  1993-06-12  |  11.7 KB  |  487 lines  |  [TEXT/PJMM]

  1. {    ircle - Internet Relay Chat client    }
  2. {    File: MsgWindows     }
  3. {    Copyright © 1992 Olaf Titz (s_titz@ira.uka.de)    }
  4.  
  5. {    This program is free software; you can redistribute it and/or modify    }
  6. {    it under the terms of the GNU General Public License as published by    }
  7. {    the Free Software Foundation; either version 2 of the License, or    }
  8. {    (at your option) any later version.    }
  9.  
  10. {    This program is distributed in the hope that it will be useful,    }
  11. {    but WITHOUT ANY WARRANTY; without even the implied warranty of    }
  12. {    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    }
  13. {    GNU General Public License for more details.    }
  14.  
  15. {    You should have received a copy of the GNU General Public License    }
  16. {    along with this program; if not, write to the Free Software    }
  17. {    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.    }
  18.  
  19. unit MsgWindows;
  20. { Deals with windows for displaying messages }
  21.  
  22. interface
  23. uses
  24.     ApplBase;
  25.  
  26. const
  27.     MW_MAGIC = 'MWIN';
  28.  
  29. type
  30.     MWHndl = ^MWPtr;    { This gets stored in the window's refCon }
  31.     MWPtr = ^MWRec;
  32.     MWRec = record
  33.             magic: OSType;            { for checking }
  34.             w: WindowPtr;            { the Window }
  35.             whenDone: ProcPtr;        { called on closing }
  36.             hscr, vscr: ControlHandle;    { scroll bars }
  37.             t: TEHandle;                { TextEdit record }
  38.             vislines: integer            { # of visible lines }
  39.         end;
  40.  
  41. var
  42.     MWActive: MWHndl;    { MWHndl of active window; or else nil }
  43.     MWdefaultFont, MWdefaultSize: integer;
  44.  
  45. procedure InitMsgWindows;
  46. { startup }
  47.  
  48. function NewMWindow (var title: string; DoWhenDone: ProcPtr): MWHndl;
  49. { Make a new window. DoWhen done gets called when user wants to }
  50. { close window; to be declared as: procedure DoWhenDone(w:WindowPtr) }
  51.  
  52. procedure SetFontSize (window: MWHndl; font, size: integer);
  53. { Change window font/size }
  54.  
  55. procedure DeleteMWindow (window: MWHndl);
  56. { Delete window }
  57.  
  58. procedure MWMessage (window: MWHndl; var msg: string);
  59. { Display message at bottom of window }
  60.  
  61. function MWFreeMem: boolean;
  62. { Tries to free up some memory }
  63.  
  64. implementation
  65.  
  66. {$SETC ZOOM=true}
  67.  
  68. const
  69.     MW_MAXLEN = 20000;     { maximum # of chars to store }
  70.     MW_KILLEN = 5000;        { # of chars to kill if window exceeds MW_MAXLEN }
  71.  
  72. {$IFC ZOOM}
  73. { a quick hack to deal with the zoom states }
  74. type
  75.     WStates = array[inZoomIn..inZoomOut] of Rect;
  76.     WStatesPtr = ^WStates;
  77.     WStatesHndl = ^WStatesPtr;
  78. {$ENDC}
  79.  
  80. var
  81.     glob: MWHndl;
  82.     cornerstone: rect;
  83.     flood: integer;
  84.  
  85. function EvtMW (var e: EventRecord): MWHndl;
  86.     var
  87.         w: MWHndl;
  88.     begin
  89.         w := MWHndl(GetWRefCon(WindowPtr(e.message)));
  90.         if w <> nil then
  91.             if w^^.magic <> MW_MAGIC then
  92.                 w := nil;
  93.         EvtMW := w
  94.     end;
  95.  
  96.  
  97. procedure SetWDimen (win: MWHndl; left, top, width, height, zoomstate: integer);
  98.     var
  99.         r: Rect;
  100. {$IFC ZOOM}
  101.         wp: WindowPeek;
  102.         zs: WStatesHndl;
  103. {$ENDC}
  104.     begin
  105. {$IFC ZOOM}
  106.         wp := WindowPeek(win^^.w);
  107.         zs := WStatesHndl(wp^.dataHandle);
  108. {$ENDC}
  109.         if left + width < 10 then
  110.             left := 10 - width;
  111.         win^^.vislines := (height - 20) div win^^.t^^.lineheight;
  112.         height := win^^.vislines * win^^.t^^.lineheight + 20;
  113.         SetRect(r, 3, 2, width - 17, height - 17);
  114.         win^^.t^^.destRect := r;
  115.         r.top := r.top + 1;
  116.         win^^.t^^.viewRect := r;
  117.         SetRect(r, left, top, left + width, top + height);
  118. {$IFC ZOOM}
  119.         zs^^[zoomstate] := r;
  120. {$ENDC}
  121.         MoveWindow(win^^.w, left, top, true);
  122.         SizeWindow(win^^.w, width, height, false);
  123.         EraseRect(win^^.w^.portRect);
  124.         MoveControl(win^^.hscr, -1, height - 15);
  125.         SizeControl(win^^.hscr, width - 13, 16);
  126.         MoveControl(win^^.vscr, width - 15, -1);
  127.         SizeControl(win^^.vscr, 16, height - 13);
  128.         TECalText(win^^.t);
  129.         TEPinScroll(0, 32767, win^^.t);
  130.         if win^^.t^^.nlines <= win^^.vislines then
  131.             SetCtlMax(win^^.vscr, 0)
  132.         else
  133.             SetCtlMax(win^^.vscr, win^^.t^^.nlines - win^^.vislines);
  134.         SetCtlValue(win^^.vscr, 0);
  135.         InvalRect(win^^.w^.portRect);
  136.         ShowWindow(win^^.w);
  137.         SelectWindow(win^^.w);
  138.     end;
  139.  
  140. procedure vscroll (o, n: integer);
  141.     begin
  142.         SetCtlValue(glob^^.vscr, o - n);
  143.         TEPinScroll(0, n * glob^^.t^^.lineheight, glob^^.t);
  144.     end;
  145. procedure Vscrolling (cc: ControlHandle; part: integer);
  146.     begin
  147.         case part of
  148.             inPageUp: 
  149.                 vscroll(GetCtlValue(glob^^.vscr), glob^^.vislines - 1);
  150.             inPageDown: 
  151.                 vscroll(GetCtlValue(glob^^.vscr), 1 - glob^^.vislines);
  152.             inUpButton: 
  153.                 vscroll(GetCtlValue(glob^^.vscr), 1);
  154.             inDownButton: 
  155.                 vscroll(GetCtlValue(glob^^.vscr), -1);
  156.             otherwise
  157.         end;
  158.     end;
  159.  
  160. function inContentHandler (var e: EventRecord): boolean;
  161.     var
  162.         p: MWHndl;
  163.         c: ControlHandle;
  164.         pa, i: integer;
  165.     begin
  166.         p := EvtMW(e);
  167.         if p <> nil then begin
  168.             glob := p;
  169.             GlobalToLocal(e.where);
  170.             pa := FindControl(e.where, p^^.w, c);
  171.             case pa of
  172.                 inUpButton, inDownButton, inPageUp, inPageDown: 
  173.                     if c = p^^.vscr then
  174.                         pa := TrackControl(c, e.where, @Vscrolling);
  175.                 inThumb: 
  176.                     if c = p^^.vscr then begin
  177.                         i := GetCtlValue(c);
  178.                         pa := TrackControl(c, e.where, nil);
  179.                         if pa = inThumb then
  180.                             vscroll(i, i - GetCtlValue(c));
  181.                     end;
  182.                 otherwise
  183.                     if PtInRect(e.where, p^^.t^^.viewRect) then
  184.                         TEClick(e.where, bitand(e.modifiers, ShiftKey) <> 0, p^^.t);
  185.             end;
  186.             inContentHandler := true;
  187.         end
  188.         else
  189.             inContentHandler := false;
  190.     end;
  191.  
  192. function inGrowHandler (var e: EventRecord): boolean;
  193.     var
  194.         p: MWHndl;
  195.         r: Rect;
  196.         ii: longint;
  197.     begin
  198.         p := EvtMW(e);
  199.         if p <> nil then begin
  200.             SetRect(r, 32, 32, 32767, 32767);
  201.             ii := GrowWindow(p^^.w, e.where, r);
  202.             inGrowHandler := true;
  203.             if ii <> 0 then
  204.                 with p^^.w^.portBits.bounds do
  205.                     SetWDimen(p, -left, -top, LoWord(ii), HiWord(ii), inZoomIn);
  206.         end
  207.         else
  208.             inGrowHandler := false;
  209.     end;
  210.  
  211. procedure XCALL (w: WindowPtr; p: ProcPtr);
  212. inline
  213.     $205F, $4E90;        { movea.l (a7)+,a0; jsr (a0) }
  214.  
  215. function inGoAwayHandler (var e: EventRecord): boolean;
  216.     var
  217.         p: MWHndl;
  218.     begin
  219.         p := EvtMW(e);
  220.         if p <> nil then begin
  221.             if TrackGoAway(p^^.w, e.where) then
  222.                 if p^^.whenDone <> nil then
  223.                     XCALL(p^^.w, p^^.whenDone);
  224.             inGoAwayHandler := true;
  225.         end
  226.         else
  227.             inGoAwayHandler := false;
  228.     end;
  229.  
  230. {$IFC ZOOM}
  231. function inZoomInOutHandler (var e: EventRecord): boolean;
  232.     var
  233.         p: MWHndl;
  234.         l, t, w, h: integer;
  235.     begin
  236.         p := EvtMW(e);
  237.         if p <> nil then begin
  238.             if TrackBox(p^^.w, e.where, e.what - mouseMsg) then begin
  239.                 HideWindow(p^^.w);
  240.                 ZoomWindow(p^^.w, e.what - mouseMsg, false);
  241.                 with p^^.w^.portBits.bounds do begin
  242.                     l := -left;
  243.                     t := -top
  244.                 end;
  245.                 with p^^.w^.portRect do begin
  246.                     w := right;
  247.                     h := bottom
  248.                 end;
  249.                 SetWDimen(p, l, t, w, h, e.what - mouseMsg);
  250.                 inZoomInOutHandler := true;
  251.             end
  252.         end
  253.         else
  254.             inZoomInOutHandler := false;
  255.     end;
  256. {$ENDC}
  257.  
  258. function updateHandler (var e: EventRecord): boolean;
  259.     var
  260.         p: MWHndl;
  261.     begin
  262.         flood := 0;
  263.         p := EvtMW(e);
  264.         if p <> nil then begin
  265.             BeginUpdate(p^^.w);
  266.             DrawControls(p^^.w);
  267.             TEUpdate(p^^.w^.portRect, p^^.t);
  268.             DrawGrowIcon(p^^.w);
  269.             EndUpdate(p^^.w);
  270.             updateHandler := true;
  271.         end
  272.         else
  273.             updateHandler := false;
  274.     end;
  275.  
  276. function activateHandler (var e: EventRecord): boolean;
  277.     var
  278.         p: MWHndl;
  279.         r: Rect;
  280.         i: integer;
  281.     begin
  282.         activateHandler := false;
  283.         p := EvtMW(e);
  284.         if p <> nil then begin
  285.             if odd(e.modifiers) then begin
  286.                 HiliteControl(p^^.vscr, 0);
  287.                 TEActivate(p^^.t);
  288.                 mwActive := p;
  289.             end
  290.             else begin
  291.                 HiliteControl(p^^.vscr, 255);
  292.                 TEDeactivate(p^^.t);
  293.                 mwActive := nil;
  294.             end;
  295.             with p^^.w^.portRect do
  296.                 SetRect(r, right - 14, bottom - 14, right, bottom);
  297.             EraseRect(r);
  298. {    InvalRect(p^^.w^.portRect);}
  299.             InvalRect(r);
  300.         end
  301.         else
  302.             mwActive := nil;
  303.     end;
  304.  
  305. function editHandler (var e: EventRecord): boolean;
  306.     var
  307.         i: integer;
  308.     begin
  309.         if mwActive <> nil then
  310.             if e.message = 4 then begin
  311.                 TECopy(mwActive^^.t);
  312.                 if ZeroScrap = 0 then
  313.                     i := TEToScrap;
  314.                 editHandler := true
  315.             end
  316.             else if e.message = 7 then begin
  317.                 TESetSelect(0, 32767, mwActive^^.t);
  318.                 SetCtlValue(mwActive^^.vscr, 0);
  319.                 editHandler := true
  320.             end
  321.             else
  322.                 editHandler := false
  323.         else
  324.             editHandler := false
  325.     end;
  326.  
  327. procedure ForceUpdate (w: MWHndl);
  328.     var
  329.         ee: EventRecord;
  330.         b: boolean;
  331.         p0: GrafPtr;
  332.     begin
  333.         GetPort(p0);
  334.         SetPort(w^^.w);
  335.         InvalRect(w^^.w^.portRect);
  336.         ee.message := longint(w^^.w);
  337.         b := updateHandler(ee);
  338.         SetPort(p0)
  339.     end;
  340.  
  341.  
  342. procedure InitMsgWindows;
  343.     var
  344.         i: integer;
  345.     begin
  346.         SetRect(cornerstone, 2, 40, 500, 40);
  347.         i := ApplTask(@inContentHandler, mouseMsg + inContent);
  348.         i := ApplTask(@inGrowHandler, mouseMsg + inGrow);
  349.         i := ApplTask(@inGoAwayHandler, mouseMsg + inGoAway);
  350. {$IFC ZOOM}
  351.         i := ApplTask(@inZoomInOutHandler, mouseMsg + inZoomIn);
  352.         i := ApplTask(@inZoomInOutHandler, mouseMsg + inZoomOut);
  353. {$ENDC}
  354.         i := ApplTask(@updateHandler, updateEvt);
  355.         i := ApplTask(@activateHandler, activateEvt);
  356.         i := ApplTask(@editHandler, menuMsg + editMenu);
  357.         mwActive := nil;
  358.         flood := 0;
  359.         MWdefaultFont := monaco;
  360.         MWdefaultSize := 9;
  361.     end;
  362.  
  363. procedure SetFontSize (window: MWHndl; font, size: integer);
  364.     var
  365.         f: FontInfo;
  366.     begin
  367.         TextFont(font);
  368.         TextSize(size);
  369.         GetFontInfo(f);
  370.         with window^^.t^^ do begin
  371.             txFont := font;
  372.             txSize := size;
  373.             lineheight := f.descent + f.leading + f.ascent;
  374.             fontascent := f.ascent;
  375.         end;
  376.         with window^^.w^.portBits.bounds do
  377.             window^^.vislines := (3 * (bottom - top - 45) div 4) div window^^.t^^.lineheight;
  378.         with window^^.w^.portBits.bounds do
  379.             SetWDimen(window, -left, -top, 80 * CharWidth('x') + 22, window^^.vislines * window^^.t^^.lineheight + 16, inZoomIn);
  380.     end;
  381.  
  382. function NewMWindow (var Title: string; DoWhenDone: ProcPtr): MWHndl;
  383.     var
  384.         h: MWHndl;
  385.         p0: GrafPtr;
  386.         r: Rect;
  387.         f: FontInfo;
  388.     begin
  389.         r := cornerstone;
  390.         OffsetRect(cornerstone, 8, 16);
  391.         h := MWHndl(NewHandle(sizeof(MWRec)));
  392.         if h <> nil then begin
  393. {$IFC ZOOM}
  394.             h^^.w := NewWindow(nil, r, title, false, 8, WindowPtr(-1), true, longint(h));
  395. {$ELSEC}
  396.             h^^.w := NewWindow(nil, r, title, false, 0, WindowPtr(-1), true, longint(h));
  397. {$ENDC}
  398.             if h^^.w <> nil then begin
  399.                 GetPort(p0);
  400.                 SetPort(h^^.w);
  401.                 h^^.magic := MW_MAGIC;
  402.                 h^^.hscr := NewControl(h^^.w, r, '', true, 0, 0, 0, 16, 0);
  403.                 h^^.vscr := NewControl(h^^.w, r, '', true, 0, 0, 0, 16, 0);
  404.                 h^^.whenDone := DoWhenDone;
  405.                 h^^.t := TENew(r, r);
  406.                 TEAutoView(false, h^^.t);
  407.                 TEActivate(h^^.t);
  408.                 SetFontSize(h, MWdefaultFont, MWdefaultSize);
  409.                 SetPort(p0)
  410.             end
  411.         end;
  412.         NewMWindow := h
  413.     end;
  414.  
  415.  
  416. procedure DeleteMWindow (window: MWHndl);
  417.     begin
  418.         HideWindow(window^^.w);
  419.         TEDispose(window^^.t);
  420.         DisposeControl(window^^.hscr);
  421.         DisposeControl(window^^.vscr);
  422.         DisposeWindow(window^^.w);
  423.         DisposHandle(Handle(window));
  424.     end;
  425.  
  426.  
  427. procedure FreeMW (window: MWHndl);
  428.     var
  429.         i: integer;
  430.     begin
  431.         i := Munger(Handle(window^^.t^^.hText), 0, nil, MW_KILLEN, ptr(1), 0);
  432.         TECalText(window^^.t);
  433.         TESelView(window^^.t);
  434.         ForceUpdate(window);
  435.     end;
  436.  
  437. procedure MWMessage (window: MWHndl; var msg: string);
  438.     var
  439.         p0: GrafPtr;
  440.         s0, s1, i: integer;
  441.     begin
  442.         if window <> nil then begin
  443.             GetPort(p0);
  444.             SetPort(window^^.w);
  445.             with window^^.t^^ do begin
  446.                 s0 := selStart;
  447.                 s1 := selEnd
  448.             end;
  449.             TEDeactivate(window^^.t);
  450.             if window^^.t^^.teLength > MW_MAXLEN then begin
  451.                 FreeMW(window);
  452.                 s0 := s0 - MW_KILLEN;
  453.                 s1 := s1 - MW_KILLEN;
  454.             end;
  455.             if pos(chr(7), msg) > 0 then
  456.                 SysBeep(10);
  457.             for i := 1 to length(msg) do
  458.                 if msg[i] < ' ' then
  459.                     msg[i] := ' ';
  460. {    msg[length(msg) + 1] := chr(13);}
  461.             insert(chr(13), msg, 1);
  462.             TESetSelect(32767, 32767, window^^.t);
  463. {    TEInsert(@msg[1], length(msg) + 1, window^^.t);}
  464.             TEInsert(@msg[1], length(msg), window^^.t);
  465.             TEAutoView(true, window^^.t);
  466.             TESelView(window^^.t);
  467.             TEAutoView(false, window^^.t);
  468.             TESetSelect(s0, s1, window^^.t);
  469.             if window^^.w = FrontWindow then
  470.                 TEActivate(window^^.t);
  471.             i := window^^.t^^.nlines - window^^.vislines + 1;
  472.             if i < 0 then
  473.                 i := 0;
  474.             SetCtlMax(window^^.vscr, i);
  475.             SetCtlValue(window^^.vscr, i);
  476. {    InvalRect(window^^.t^^.viewRect);}
  477.             SetPort(p0);
  478.         end;
  479.     end;
  480.  
  481. { by now it's a dummy :-) }
  482. function MWFreeMem: boolean;
  483.     begin
  484.         MWFreeMem := false;
  485.     end;
  486.  
  487. end.